package com.monitor.config;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.monitor.entity.pojo.user.User;
import com.monitor.module.permission.service.PermissionService;
import com.monitor.module.role.service.RoleService;
import com.monitor.module.user.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.data.redis.RedisConnectionFailureException;
import org.springframework.data.redis.core.RedisTemplate;

import javax.annotation.Resource;
import java.util.HashSet;
import java.util.Set;

/**
 * 自定义Realm.
 *
 * @author Li Zhiyuan
 * @since 2020-11-10
 */
@Slf4j
public class MyRealm extends AuthorizingRealm {

    @Resource
    private UserService userService;
    @Resource
    private RoleService roleService;
    @Resource
    private PermissionService permissionService;

    @Resource
    private RedisTemplate<String,User> redisTemplate;


    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        // 获取用户名
        String username = (String) principals.getPrimaryPrincipal();
        // 根据用户名查询user信息
        User user = userService.getOne(Wrappers.<User>lambdaQuery().eq(User::getUserName, username));
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        //给该用户设置角色，角色信息存在t_role表中取
        Set<String> setRoles = new HashSet<>();
        setRoles.add(roleService.getById(user.getRoleId()).getRoleName());
        authorizationInfo.setRoles(setRoles);
        //给该用户设置权限，权限信息存在t_permission表中取
//        List<Permission> permissionList = permissionService.list(Wrappers.<Permission>lambdaQuery().eq(Permission::getRoleId, user.getRoleId()));
//        Set<String> setStringPermissions = new HashSet<>();
//        permissionList.forEach(l -> setStringPermissions.add(l.getPermissionName()));
//        authorizationInfo.setStringPermissions(setStringPermissions);
        return authorizationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //根据token获取用户名
        String username = (String) token.getPrincipal();
        //根据用户名从数据库中查询该用户
        User user = userService.getOne(Wrappers.<User>lambdaQuery().eq(User::getUserName, username));
        if (user != null) {
            //把当前用户存在session中
//            SecurityUtils.getSubject().getSession().setAttribute("user", user);
            log.info("session==========={}", (String) SecurityUtils.getSubject().getSession().getId());

            try {
                if (redisTemplate.opsForHash().size(username)==0) {

                    redisTemplate.opsForValue().set(SecurityUtils.getSubject().getSession().getId().toString(), user);
                    redisTemplate.opsForHash().put(username, SecurityUtils.getSubject().getSession().getId().toString(), user.getName());
                    redisTemplate.opsForHash().values(username);
                    redisTemplate.opsForHash().entries(username).keySet().forEach(l->l.toString()) ;
                }else {
                    redisTemplate.opsForHash().entries(username).keySet().forEach(l->redisTemplate.opsForHash().delete(username,l)) ;
                    redisTemplate.opsForHash().put(username, SecurityUtils.getSubject().getSession().getId().toString(), user.getName());
                }


            }catch (RedisConnectionFailureException e){
                throw e;
            }
                //传入用户名和密码进行身份认证，并返回认证信息
                AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user.getUserName()
                        , user.getPassWord(), "myRealm");
                return authenticationInfo;

        } else {
            return null;
        }
    }
}
